home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Sound Fx
/
Sound Fx.iso
/
Software
/
UNZIPED
/
DWSTKW
/
DOC
/
WINSTK.TXT
< prev
Wrap
Text File
|
1996-09-23
|
88KB
|
2,059 lines
This document is pure ASCII text format; it may be viewed in any text editor,
or by the "type" command at a DOS prompt. It's not really optimized for
printout; if you want a hardcopy, we really recommend printing from WINSTK.DOC
(which is in Microsoft Word format). It will give you nice pagination,
courier monospace and other fonts, a table of contents, an index, etc.
DiamondWare's Sound ToolKit for Windows (The WIN-STK) was brought to
you by DiamondWare, Ltd.
You can contact us via:
internet email: support@dw.com
Web Page: www.dw.com
CompuServe: 73704,245
voice: (602) 917-3474
FAX: (602) 917-5973
snail-mail: 2095 N. Alma School Rd., Suite 12-288, Chandler, AZ 85224
The WIN-STK software was designed and developed by John C. Lundy, Erik
Lorenzen, and Keith Weiner.
Example source code was developed by John Lundy, with language-specific
help from Dave Allen (Visual BASIC), and David Bollinger (Delphi).
This document was written and edited by Keith Weiner. Proofreading was done
by Joyce Weiner, Angelo Nunes, Erik Lorenzen, John Lundy, Dave Allen and
David Bollinger.
The Visual BASIC interface was written by Dave Allen. The Delphi interface
was written by David Bollinger.
This software and documentation are Copyright 1994-1996 DiamondWare,
Ltd. All rights reserved. DiamondWare's Sound ToolKit, DiamondWare's
STK, The STK, The WIN-STK, DiamondWare, DW, and DW are trademarks of
DiamondWare, Ltd.
The included sample MIDI song is Copyright 1994 David Schultz, All Rights
Reserved. Used by permission. May not be used without written permission
from David Schultz.
DiamondWare also offers a full range of consulting and software development
services, from device-driver development to turnkey multimedia titles. Please
call us for more information.
Borland is a registered trademark, and Delphi is a trademark of Borland
International Inc.
Visual Age is a trademark, and IBM is a registered trademark of IBM Corp.
Microsoft and Win32 are registered trademarks of, and Windows and Visual
BASIC are trademarks of Microsoft Corporation
Symantec is a trademark of Symantec Corporation
Watcom is a trademark of Watcom Systems, Inc.
License Agreement: Commercial Version
This document is a legal agreement between you and DiamondWare, Ltd. By using this software,
you agree to be bound by the terms of this Agreement and Disclaimer of Warranty and Limited
Warranty. If you do not agree to the terms of this Agreement, promptly return the software and all
accompanying items for a full refund.
1. GRANT OF LICENSE. This License Agreement permits you (one person) to use one copy of the
enclosed Sound ToolKit for Windows software and documentation (The WIN-STK) on a single
computer.
2. COPYRIGHT. The WIN-STK is owned by DiamondWare, Ltd., and is protected by United
States copyright law and international treaty provisions. You must treat the WIN-STK like any
other copyrighted work except that you may either (a) make one copy solely for backup or archival
purposes, or (b) transfer the WIN-STK to your hard disk, provided that you keep the original solely
for backup or archival purposes. You may not copy the written materials accompanying the WIN-
STK. You may be held legally liable for any copyright infringement that is caused or encouraged
by your failure to abide by the terms of this Agreement.
3. OTHER RESTRICTIONS. You may not rent or lease the WIN-STK. It is licensed to you, the
Licensee. The license may not be transferred to any other party without the prior written consent of
DiamondWare, Ltd. You may not reverse engineer, decompile, or disassemble the WIN-STK.
4. DISTRIBUTION. You are hereby granted a royalty-free non-exclusive right to reproduce and
distribute the WIN-STK DLLs as part of your software, provided that it does not compete with, or
substantially duplicate the functionality of, the WIN-STK. You must credit the WIN-STK wherever
your other credits appear.
License Agreement: Demo Version
This version of the WIN-STK is SHAREWARE. DiamondWare grants you a personal license to
evaluate the WIN-STK for 30 days. This license is for evaluation purposes only. You may not
distribute this SHAREWARE version of the WIN-STK as part of any other software. In any event,
after 30 days, you must pay the license fee or stop using the STK.
DiamondWare also grants permission to distribute this SHAREWARE version of the WIN-STK
under the following terms:
1. You must include all of the files listed in PACKING.LST.
2. You must make it clear that the WIN-STK is SHAREWARE.
Disclaimer of Warranty and Limited Warranty
The WIN-STK diskette and accompanying written materials are sold "as is", without warranty or
guarantee as to their performance, merchantability, or fitness for any particular purpose. The entire
risk as to the results and performance of the WIN-STK is assumed by you.
However, the magnetic diskette on which the software is recorded is warranted to be free from
defects in materials and workmanship under normal use for a period of ninety days from the date of
purchase. If, during this ninety-day period, the diskette should prove defective, it may be returned
for a replacement without charge, provided you have registered your WIN-STK license via mail.
Your sole and exclusive remedy in the event of a defect is expressly limited to replacement of the
diskette, as provided above.
Any implied warranties relating to the diskette, including any implied warranties of
merchantability and fitness for a particular purpose, are limited to a period of ninety days from the
date of purchase. Neither DiamondWare, nor its partners, agents, distributors, or contractors, shall
be liable for indirect, special, or consequential damages resulting from the use of this product.
Free Upgrade Policy for Bug Finders
DiamondWare is committed to the goal of zero-defect software.
Bug-free programs do not happen by accident. They are the result of a thorough
design, a scientific approach to coding, and extensive testing of the finished
product. By the time we ship a product, we have more than just a hope that our
products are robust. We have an expectation, based on evidence.
You shouldn't find any bugs in our code.
But if you do, your foremost concern (and ours) is getting the problem fixed
properly, verifying the fix, and getting you an update.
For your trouble, we're prepared to offer you a free upgrade to the next major
version. This isn't really adequate payment for your time or aggravation. But
it's our way of showing some appreciation for what is otherwise a grueling and
thankless task.
Conditions
The defect must be non-trivial.
You must be the first to report it.
Upon our request, you must provide us with a test program which
demonstrates the bug.
The bug must be caused by DiamondWare's code.
Cosmetic problems are excluded from this policy, although we'll try to
provide fixes quickly.
Operating system or driver bugs are also excluded, although we'll try to
provide workarounds.
The final decision, whether or not to award a free upgrade, lies with
DiamondWare.
Please help us make the product better by reporting any problem you encounter
with DiamondWare software.
Upgrade Policy
It's our policy to make minor version upgrades available to registered users of
our products free of charge.
Minor version upgrades include bug fixes, performance improvements,
additional new features, etc.
Normally, minor version upgrades are distributed electronically.
Major version upgrades will constitute at least one non-trivial new feature, and
several other features. A major version means that substantial new code was
developed; possibly the product was rewritten from the ground up.
New major versions are offered to existing customers at a substantial discount;
in the past, the discount has been 50%.
Introduction
This manual is organized into three major sections. The first is the Guide.
Although you can skip the some of its topics, it contains some invaluable
information about the WIN-STK, including useful hints and troubleshooting
help.
The second section is the Tutorial. It will take you step by step through some
code which uses the STK. If you're familiar with the DOS-STK, or prefer to
read the files on disk, you might skip this section; it is not essential.
The third section is the Reference. You might want to skim it before writing
your code; it's always a good idea to achieve closure with any API you use.
Guide to the WIN-STK
This section gives an overview of the product, but also contains some specific
information, and recommendations.
What Is It?
DiamondWare's Sound ToolKit for Windows (The WIN-STK) is a sound library
which provides functions to support interactive sound and music.
What does this mean? Windows can play MIDI and WAVE files already.
That's true. However, Windows cannot play more than one sound at a time, nor
even reliably tell you when it's done playing. The rest of this Guide will discuss
the feature set of the WIN-STK, and explain how to use it.
The WIN-STK is supplied as four DLLs: one for 16- and one for 32-bit Windows
(and two more for Win32s), so it can be used from almost any programming or
authoring environment. We provide all the files you'll need if you're using
C/C++ from Microsoft, Borland, Watcom, Symantec, or IBM; or if you're using
Visual BASIC, or Delphi.
The WIN-STK implements a superset of our acclaimed API, originally
introduced for the DOS version. Its architecture will impact yours minimally (if
at all), so adding the WIN-STK to a mostly-completed program will be easy.
The WIN-STK provides an object-oriented sound-centered API, which is
cleaner and easier to use than a channel-centered system. With the WIN-STK,
you don't have to allocate or deallocate channels.
The WIN-STK supports (and has been tested under!) Windows 3.1, Windows
95, and Windows NT.
The WIN-STK requires a minimum platform of a 486. We recommend a 486-
66, however.
What Does It Do?
It plays up to sixteen digital sounds (WAVEs) at the same time, plus one MIDI
song. Your program selects the digitized mode (mono or stereo, bits/sample,
and sampling rate) and which MIDI device to use.
The salient features of the WIN-STK are listed below.
Random Access. You can start or stop any sound at any time.
Low latency. Latency is the time elapsed between your call to play a sound,
and when the sound is actually heard. Typically, for Windows 95 and NT, the
WIN-STK latency figures are: 100 milliseconds average, 75ms best case, and
125ms worst case. For Windows 3.1, they are 200ms average, 150 best, and
250 worst. This is good enough to convince users that a sight and sound
occurred simultaneously. (Though it's probably not good enough for a
keyboard synthesizer application.)
DSP. You can alter the pitch and volume of each sound.
Stereo. The WIN-STK can play a monophonic (or stereo sound) through both
stereo output channels, with a different volume in each (panning).
Interactivity. Even after a sound is playing, you can change its pitch and
volume, loop count, etc. The WIN-STK can notify you when a sound is done
playing, giving you the opportunity to display graphics or execute a handler.
Sequencing. The WIN-STK allows you to play a sound right after another,
guaranteeing that the sequenced sound will play exactly when the first is done,
without an overlap, click, or pause.
Music. The WIN-STK can play a MIDI song.
Where Is It Going in the Future?
This version of the WIN-STK was released because it provides a valuable
feature set to many programmers, who are trying to mix several channels of
digital audio.
But it's not the penultimate system. Here's sneak preview of future WIN-STKs.
Better MIDI support. This includes volume control, callbacks for SysEx and
other events, multiple songs playing at the same time, segueing, branching, etc.
In other words, interactive music.
DirectSound and Native Audio support.
Recording. A future version will support recording, as well as playback. Added
bonus: some boards support simultaneous record/playback, which is perfect for
networked games!
Other features, To Be Determined: If there's something you really want to see,
please let us know!
Development Environments
Before proceeding any further, you should be familiar with such programming
topics as bitfields and using DLLs.
The WIN-STK will work with any development environment which can load
and call DLLs, however this document discusses C/C++, Visual BASIC, and
Pascal specifically.
Language Notes for C/C++
The WIN-STK has been tested with compilers from Microsoft, Borland,
Watcom, Symantec, and IBM. DWS.H passes through all of them without any
warnings. The sample program PLAYSTK also works with all. However, we
provide a 16- and 32-bit .LIB file for each compiler.
In some compilers, you may need to add the common dialog library into your
project in order to build PLAYSTK.EXE. See your compiler's manual for
details.
This manual was written using C terminology, so if you're familiar with ANSI
C, and a modern commercial Windows compiler, you should be able to read this
manual with 100% comprehension.
As with other libraries, the WIN-STK provides an include file. Put the line:
#include "dws.h"
at the top of every source module which uses the WIN-STK.
If you've never written a program using a DLL before, there are two ways to do
it. We'll call the first "The Easy Way", and the second "The Hard Way."
In The Easy Way, you link with an import library. This usually comes with the
DLL, or most compilers provide a utility called IMPLIB.EXE which can make
one. The import library provides a stub for each function in the DLL. It takes
care of the magic of loading the DLL, determining runtime addresses, etc.
The WIN-STK comes with an import library for the most popular compilers; if
we didn't provide one for your compiler, look for IMPLIB.EXE in your
compiler's BIN directory.
In The Hard Way, you do everything yourself. You manually load the DLL,
calculate the address of every function you need within it, and call those
functions through pointers. The Hard Way is beyond the scope of this
documentation, but it's mentioned for completeness.
Some programmers use the standard-library function atexit to register
cleanup functions, which are called before the program terminates. You must
not use this facility to call dws_Kill. This is because Windows 95 and NT
will wait until all threads except the main thread stop executing. The WIN-STK
uses a background thread which is terminated during the call to dws_Kill.
This will lead to an impasse, where the program will not quite terminate.
The atexit problem does not apply to 16-bit programs, but if you think that
you will ever move to Win32, you should probably avoid it anyway.
Language Notes for Visual BASIC
The WIN-STK supports Visual BASIC 3 and Visual BASIC 4, including the
new 32-bit mode.
In the reference section, you will find a prototype for each WIN-STK function
in C, Visual BASIC, and Pascal. However, this document is somewhat C-
centric.
Read on for some information which will help you comprehend the rest of the
manual.
In C, all procedures are called "functions", although in Visual BASIC they may
be "functions" or "subroutines", depending on whether they return a value.
In C, variables are declared type first, and then variable name:
int x;
This declares a variable called x, of type integer. Pointers are declared with a
star, like:
int *y;
Here, y is a pointer to integer. Some WIN-STK functions take pointer
parameters, and the sample C code in this document will use this notation.
A C struct, often called a structure, is the equivalent of a Visual BASIC user-
defined Type.
C comments are either a double slash //Comment which is a comment until
the end of the line, equivalent to Visual BASIC's apostrophe ' or REM; or
/*Comment*/, which is a comment between the /* and the */.
C expresses bitwise OR as a pipe |, bitwise AND as an ampersand &, boolean
OR as two pipes ||, and boolean AND as two ampersands &&.
In C, the ampersand & operator can also be used to take the address of a
variable. For example:
dws_MSongStatus(&mstat);
This call passes the address of the variable mstat to dws_MSongStatus.
By default, Visual BASIC passes parameters by reference, so you probably
won't have to deal with this issue.
In C, the default is to pass a parameter by value, which in VB requires the use of
the ByVal keyword.
To pass a NULL pointer in Visual BASIC, you need to specify a 32-bit 0:
dws_DGetInfo(dplay, ByVal 0&);
We provide DWS.BAS, which declares all of the constants, data types, and
routines of the WIN-STK. Add this file to your project. You might also want to
read through it.
The WIN-STK can send your window a message when a digitized sound is done
playing. But Visual BASIC alone does not allow you to receive or process
specific window messages. You will need a third-party VBX or OCX control to
use this feature.
Language notes for Pascal
The WIN-STK works with the various Windows Pascal products published by
Borland. However, the sample program PLAYSTK, will only compile with
Delphi.
In the reference section, you will find a prototype for each WIN-STK function
in C, Visual BASIC, and Pascal. However, this document is somewhat C-
centric.
Read on for some information which will help you comprehend the rest of the
manual.
In C, all code routines are called "functions", although in Pascal they may be
"functions" or "procedures", depending on whether they return a value.
In C, variables are declared type first, and then variable name:
int x;
This declares a variable called x, of type integer. Pointers are declared with a
star, like:
int *y;
Here, y is a pointer to integer. Some WIN-STK functions take pointer
parameters, and the sample C code in this document will use this notation.
A C struct, often called a structure, is the equivalent of a Pascal record.
C comments are either a double slash //Comment which is a comment until
the end of the line or /*Comment*/, which is equivalent to Pascal's
(*Comment*).
C expresses bitwise OR as a pipe |, bitwise AND as an ampersand &, boolean
OR as two pipes ||, and boolean AND as two ampersands &&.
In C, the ampersand & operator can also be used to take the address of a
variable. For example:
dws_MSongStatus(&mstat);
This call passes the address of the variable mstat to the function (which puts
the song's status into the variable). This is equivalent to Pascal's var calling
convention.
We provide DWS.PAS, which declares all of the constants, data types, and
routines of the WIN-STK. You will need to insert the line:
uses dws;
into your main program. You might also want to read the source.
Pascal is not case-sensitive. This will cause the dws_DPLAY and dws_MPLAY
record types to conflict with the corresponding function names. Therefore, they
have a REC at the end (e.g. dws_DPLAYREC and dws_MPLAYREC).
In Pascal, the identifier message is a keyword. Therefore in Pascal, the
message field in the dws_DPLAY record is renamed wmessage.
Another problem with Pascal and the WIN-STK is that the functions
dws_DGetInfo and dws_DSetInfo take two dws_DPLAYREC parameters
which are passed by reference (declared as var). To tell these functions to
ignore a parameter, C and Visual BASIC programmers can pass a NIL. The
Pascal compiler will not let you do this directly. But there is another way of
indicating "ignore this parameter". The dws_DPLAYREC record has a flags
field which indicates which other fields within the record you are using. If you
set flags = 0, then the WIN-STK will behave exactly as if you had passed
NIL as the address of the record. See the Reference section for more details.
The dws_WAV2DWD function also accepts a NIL pointer in certain cases.
However, the parameter is not a pass-by-reference variable in this function. It's
a PBYTE, so the compiler will let you pass NIL.
This document will not further refer to these differences between Pascal and C.
Installing the WIN-STK
Simply copy (or unzip) the WIN-STK files into their own subdirectory tree on
your hard drive. There are different subdirectories for C, Visual BASIC, Pascal,
the DLLs, etc. You probably don't need all of them.
Make sure you put the files for your language where your compiler and linker
can find them. If you need more information on this and related topics, your
compiler's manual will be far more detailed than is possible here, and will cover
your specific software environment.
Installing a WIN-STK-using Program
When you install your program on the user's machine, please put the WIN-STK
DLLs in the same directory as your executable(s). This will ensure that other
programs using different versions of the WIN-STK will coexist with yours. In
fact, this is a good practice for all DLLs in Windows.
Using the WIN-STK Effectively
The Tutorial and Reference sections describe, in great detail, how to use the
WIN-STK. Here, we discuss some of the issues to think about if you want to
use the WIN-STK effectively.
Stereo or Mono?
The WIN-STK can output stereo or mono sound. In most cases, you will want
to use stereo if supported by the hardware. Elsewhere in this manual, you'll
find out how to determine if stereo is available. You might want to use mono,
however, to save precious CPU cycles on slower machines. Elsewhere, we
discuss other things to do to maximize performance.
So you've decided to use stereo. But have you thought about your source
sounds? Should you record them in stereo?
The answer depends on what you are trying to do. If you are playing any kind
of cinematic sequence, then stereo recording is probably appropriate.
But if you want your sound to be interactive, then mono is probably a better
choice because the WIN-STK can play the left and right channels at different
volume levels. This is called panning, and can be used to communicate a
sound's location to the user. In fact, many 3D games use panning to localize
sound.
Authoring Sound
If you're authoring a long playback sequence, with little or no interactivity to it,
you may author literally anything which the hardware can play back. The
sampling rate, sample size, and whether to use stereo will be dictated by your
creative designer, and storage considerations.
But if you're producing sound to be played simultaneously with other sounds
and be manipulated by the program, read on.
The first issue to consider is dynamic range. In digital sound playback, there is
always a limit to how loud a sample can be. All overflows must be clipped. If
an occasional sample is clipped, then the user will most likely never notice it.
However, if you overload the system with many loud sounds, then the output
will sound distorted, which is usually undesirable.
Record your sounds so that they do not use a lot of dynamic range. The goal is
to minimize the difference between the loud parts and the soft parts, making the
entire sound somewhat quiet. Good sound editing programs offer a dynamic
range compression feature for just this purpose.
Keep the overall volume level of your sounds commensurate with how many
you expect to play at the same time. For example, if you need to play four
sounds at a time, then each sound should use roughly ¼ of the total dynamic
range.
If you're going to use volume panning to localize sounds, then you will likely
want distant sounds to be quiet and close sounds to be loud. In this case, record
your sound at the loudest level you'll need, and use the WIN-STK to make it
softer as it moves into the distance.
This will give you better sound quality (as well as being computationally
faster-see the next topic for details) than recording soft and raising the volume
at runtime.
WIN-STK Performance
8-bit audio is less CPU intensive than 16-bit. Using 8-bit also allows the WIN-
STK to perform certain additional optimizations.
So what's the order of fastest to slowest modes? 8-bit mono is fastest, followed
by 16-bit mono, then 8-bit stereo, then 16-bit stereo. The difference between
16-bit mono and 8-bit stereo is slight.
There is a tradeoff between latency (the time between when your program calls
a sound function, and the time when the user hears it) and CPU usage. A
smaller internal buffer will allow the WIN-STK to give you lower latency, but it
will need to be updated more often, thus increasing the CPU load.
Sound, unlike video, can't acceptably stall even briefly. If the buffer is not
updated by the deadline, an audible gap or click will result. Slower computers,
of course, will take more time before they can get around to updating the buffer.
Thus, the WIN-STK will use larger buffers on slower machines, and can get
away with smaller buffers on faster machines.
The WIN-STK can play up to 16 digital sounds at the same time. But you
should configure the WIN-STK to allow only for the maximum number of
voices your program will actually use. Setting this value needlessly high will
impose CPU usage and latency penalties.
It's important to understand that the WIN-STK will convert sounds (if
necessary) to the match the output mode. Thus, even if the output mode is 8-bit
mono, you can still play a 16-bit stereo file.
Obviously, you should author your sounds with the same sample size and
number of channels as your intended output mode. You should only rely on the
WIN-STK's automatic format conversions if a user's sound hardware is less
capable than your target platform. But in any event, the WIN-STK can exploit
the 8-bit optimizations if either the source sound, or the output mode, is 8-bit.
Volume change is always faster than pitch change. Lowering the pitch is always
faster than raising it.
With 8-bit sound, lowering the volume is faster than raising the volume. With
16-bit sound, there is no difference in CPU usage.
16-bit vs. 32-bit DLLs
The 16-bit DLL works under Windows 3.1, Windows 95, and Windows NT.
The 32-bit DLL works only under Windows 95, and NT because it makes
extensive use of multithreading.
16-Bit
The 16-bit DLL is susceptible to all of the problems you normally have in
Windows 3.1. If your application hogs the CPU for a while, then the WIN-STK
might stop playing sound until you yield again. To get around this problem, we
provide a function (dws_Update) that you can call to keep the sound going,
even if you don't want to yield to the system.
If another application hogs the CPU (or if your user drags your window around
by the title bar), then the sound will pause. There isn't anything that anyone can
do about it.
32-Bit
The 32-bit DLL is immune to the above problems; Win32 is a superior platform
to Win16!
Be aware, however, that if you really hog the CPU within a very high-priority
thread, you can cause the sound to pause. You probably shouldn't be doing this,
but if you must, then you must call dws_Update periodically. High-priority
threads should only be used for fast, critical actions.
The 32-bit DLL is fully thread-safe.
The WIN-STK kernel thread runs at THREAD_PRIORITY_TIME_CRITICAL
priority. This results in a base priority level of 15 for calling processes with a
priority class of IDLE_PRIORITY_CLASS, NORMAL_PRIORITY_CLASS, or
HIGH_PRIORITY_CLASS; and a base priority level of 31 for processes with
REALTIME_PRIORITY_CLASS. You should think long and hard before you
set your priority class to anything above HIGH_PRIORITY_CLASS!
Latency vs. Smooth Playback
There is a tradeoff between minimizing the latency, and playback which never
skips. Latency is directly proportional to buffer size. But larger buffers offer
immunity to skipping. The WIN-STK autodetect function can do a pretty good
job calculating the buffer size on most machines, but it may not be perfect.
You might provide a slider bar for the user to make changes to the calculated
buffer size.
Digitized Sound Theory
This section presents a basic description of digitized sound, and some of the
theory. You don't really need to read this, but you may find it interesting and
useful in the future. Digitized sound on computers will certainly be used in the
future.
Digitized sound is sound that has been sampled, or quantized. Periodically, the
analog voltage of a sound signal is measured by a special circuit called an
Analog to Digital Converter (ADC), and then stored.
Digitized sounds are discretely quantized. This means that there is a finite set of
possible values for each sample. It also means that there are only samples for a
finite number of instants in time.
Let's take the case of 8-bit samples. Samples range from -128 to +127. Any
sound softer than +/-1 is lost. Any sound louder than +127/-128 will be clipped,
which sounds bad. This overflow problem is compounded if you're mixing
several sounds together, or processing the sound digitally.
Just as the range of samples is not infinite, neither is the domain. Digitized
sounds are not contiguous in the time domain. They're sampled at T=1 and
T=2, but not at T=1.5. There's obviously sound at every moment, even during
those in between the sample points. But we have no record of it; a graph of
digitized sound data has a characteristic stair-step shape. We'll look at the
problems this can cause below.
Digital signal theory asserts that every possible waveform can be represented by
the sum of a finite series of pure sine waves. The highest frequency sine wave
in this series is no higher than the highest frequency component present in the
original wave.
The Nyquist theory of digital signal processing states that, in order to capture a
waveform containing frequencies up to F, you need to sample it at a rate of at
least 2F.
Any sampling rate, R, lower than 2F will cause the frequencies above R / 2 to be
aliased as lower frequencies. This sounds like a metallic overtone on top of the
original sound.
To visualize this better, think of the infamous problem of drawing a diagonal
line on a low-resolution screen, or of watching a spinning propeller seem to turn
slowly backwards. The sampling rate (resolution) of the screen is too low to
display the line. The sampling rate of the human eye is too low to see a 15,000
RPM propeller.
When we convert digital samples back to analog, the result looks quite square
(the stair-step shape mentioned above), and not at all like the original. This is
an immutable consequence of the process.
The steep vertical segments in the wave are high frequencies. Therefore, you
must send the signal through a low-pass filter to remove the extra garbage.
Sound boards all contain low-pass filters for this very reason. In practice, a
cheap set of speakers would probably act as an effective filter for the higher
sampling rates.
Although the following doesn't really relate to computer audio, it's interesting
because it's relevant to every CD player.
Analog filters distort the sound. The steeper the cutoff, the worse they sound.
So instead of trying to build a filter which passes everything below 20,000 Hz
and cuts everything above 20,001 Hz, CD players use oversampling. You can
think of oversampling as "interpolation".
If you convert the sample data to the frequency domain, add extra zeroes for all
the frequencies above your actual sound data, and convert back to the time
domain, you'll have a smoother interpolation of the original sound. More
importantly, the harmonic overtones will be at a higher frequency, and thus
easier to filter.
So the next time you buy a CD player, don't let the ignorant salesman tell you
that ".THIS player reads the disc eight times so it doesn't make as many
errors.". You know now that oversampling is just a technique to produce
smoother output. Even cheap CD players can read a disc without errors, or else
CD-ROM's would never work!
Tutorial
This section will take you through the steps required to add sound to a C
program, starting with the barest minimum, and leading up to some more
advanced concepts and features. Every line of code should easily convert to an
equivalent line in Visual BASIC or Pascal.
The code does not check for errors, or do any of the other things required of
robust, commercial-quality code.
Caveat: This code has not been tested or compiled! It's good for reading
through, and to illustrate key WIN-STK implementation issues. But, you're
better off cutting code out of PLAYSTK than attempting to use the code
presented here.
The Basics
The Variables
void PlaySoundAndSong(void)
{
FILE *fp;
BYTE *sfx;
WORD mstatus;
WORD dsize;
dws_DETECTRESULTS dres;
dws_IDEAL ideal;
dws_MPLAY mplay;
dws_DPLAY dplay;
We're going to load one sound effect from disk into memory (MIDI songs are
played directly from disk file). sfx, a pointer, holds the address of the sound
effect buffer. dres, and ideal are structs required for initialization. dplay,
a struct, holds all information needed to play the sound effect; mplay, another
struct, holds information for playing the song.
Loading Songs and Sounds
/* Allocate memory */
fp = fopen("sample.dwd", "rb");
fseek (fp, 0L, SEEK_END);
sfx = malloc(dsize = ftell(fp));
/* Load the sound file */
fseek(fp, 0L, SEEK_SET);
fread(sound, dsize, 1, fp);
fclose(fp);
This code allocates a buffer to store the sound, and then reads the sound file into
it. SAMPLE.DWD began as SAMPLE.WAV (an 8-bit mono digitized sound,
sampled at 11kHz), and was converted by WAV2DWD.EXE.
Initializing the STK
/* Run the WIN-STK's autodetect routine */
dws_DetectHardWare(&dres);
/* Init the WIN-STK */
ideal.mustyp = dws_muscap_MAPPER;
ideal.digtyp = dws_digcap_11025_08_1;
ideal.dignvoices = 2;
ideal.flags = dws_ideal_NONE;
dws_Init(&dres, &ideal);
The results of the autodetect are returned in the dres struct.
This code fails to check to see whether the WIN-STK even found a MIDI
mapper, but just assumes that it's there. The MIDI mapper is installed on most
machines, but you can't make an assumption like that in real code!
We initialized the ideal struct to request the desired STK services. Note how
we specified 2 voices. This allows the WIN-STK to run at its most efficient.
Don't tell the WIN-STK to use any more voices than you need.
After the call to dws_Init, the sound hardware and the WIN-STK are set up
for business.
Preparing Songs and Sounds
/* Prepare to play song */
mplay.track = "sample.mid";
mplay.count = 1;
/* Prepare to play digitized sound */
dplay.flags = dws_dplay_SND;
dplay.snd = sound;
The mplay struct and the dplay struct are set up prior to the calls to play
them. The flags field in the dplay struct tells the WIN-STK which fields
have been initialized. Since we didn't use most of the fields in the struct, they'll
take on reasonable defaults (see the Reference section for specifics).
Starting Playback
/* Play song and sound */
dws_MPlay(&mplay);
dws_DPlay(&dplay);
A call to dws_MPlay starts the music, and a call to dws_DPlay begins
playback of the digitized sound effect.
The flags field in the dws_DPLAY struct was designed to allow you to use as
many or as few of the features available through the dws_DPlay function as
you want. At a minimum, you must set dws_dplay_SND. This indicates that
you have specified a pointer to a sound buffer. All other fields (e.g. pitch, loop
count, etc.) are optional. The flags mechanism also protects your program from
breaking when you upgrade to new WIN-STK releases. If there are new
features, your program won't inadvertantly use them.
Wait 'Til the Fat Lady Stops Singing
/* Wait loop */
do
{
dplay.flags = dws_dplay_SOUNDNUM;
dws_DGetInfo(&dplay, NULL);
dws_MSongStatus(&mstatus);
} while ((dplay.soundnum) ||
(mstatus & dws_MSONGSTATUSPLAYING));
To query the sound's status, we call dws_DGetInfo, and look at the
soundnum field that it sends back to us. When the sound is done playing, this
field is returned as 0.
Note that if you simply want to play a sound, and wait until it's done playing,
there's an easy way to do this: simply set the dws_dplay_SYNCHRONOUS
flag field. This will cause the WIN-STK to wait until the sound is done playing
before it returns to your program. While it's waiting, it yields to the system.
To query the song's status, we call dws_MSongStatus, with the address of a
bitfield variable. We're interested in the dws_MSONGSTATUSPLAYING field.
Shutting Down
/* Free the memory we allocated above */
free(sound);
/* We must kill the WIN-STK */
dws_Kill();
}
Normally, you would call dws_DDiscard before freeing a sound buffer, but
in this case, we know that the sound is done.
The Fancy Stuff
The WIN-STK does a whole lot more than what we've seen so far. In this topic,
we'll show you how to play more than one sound at the same time (which is
called "polyphony"), how to sequence a sound after another, how to use the
WIN-STK's built-in volume and pitch control, how to change sounds once
they're playing, how to get notification that a sound is done playing, how to
play large files from disk (32-bit DLL only), and how to handle WIN-STK
errors.
Polyphony
The WIN-STK kernel was designed to be polyphonic from the ground up, so
you don't need any special tricks. To play two or more sounds at the same time,
simply call dws_DPlay more than once.
The example code fragment below assumes that the WIN-STK has been
initialized. sfx1 and sfx2 are digital sounds in memory.
dplay.flags = dws_dplay_SND |
dws_dplay_PRIORITY;
dplay.snd = sfx1;
dplay.priority = dws_NORMALPRIORITY;
dws_DPlay(&dplay);
dplay.snd = sfx2;
dplay.priority = dws_NORMALPRIORITY;
dws_DPlay(&dplay);
The priority field helps the WIN-STK determine which sound to drop if you
exceed the maximum number of voices (specified in the dws_IDEAL struct in
the call to dws_Init). The issue is moot for this example, but may be a factor
in a real-world application.
Note that you can reuse the dplay struct itself; all WIN-STK functions copy
what they need from your structs before returning.
Sequencing
Sequencing allows you to play a sound back-to-back with another. The first
sample of the sequenced sound plays right after the last sample of the first
sound. The effect is that of a single sound playing seamlessly, without a pause
or even a click.
The presnd field of the dws_DPLAY struct is the key to this feature. To
sequence sound B after sound A, then set the presnd field of sound B's
dplay struct to the soundnum of sound A (set by the call to dws_DPlay).
In the example below, assume that dplay1 and dplay2 are both structs of
type dws_DPLAY.
dplay1.flags = dws_dplay_SND;
dplay1.snd = sfx1;
dws_DPlay(&dplay1);
dplay2.flags = dws_dplay_SND | dws_dplay_PRESND;
dplay2.snd = sfx2;
dplay2.presnd = dplay1.soundnum;
dws_DPlay(&dplay2);
This example tells the WIN-STK to wait until the first sound is complete, and
then play the second.
The WIN-STK will set the soundnum field of dplay2 to the same value as its
presnd; no matter how many sounds you sequence, they will all have the same
soundnum.
Note: if you have want to play a sequence of more than two sounds, then some
manual effort is required; the WIN-STK handles only two at a time: the one
that's playing, and the one sequenced after it. You must wait until the first
sound is done (and hence the sequenced sound is playing) before sequencing the
third. Use dws_DGetInfo to determine when a sound is done.
Sequencing is useful if you want to break a long sound into several pieces. Or,
if you want to play a sound, and then "branch" to one of several sounds,
depending on some user-interaction after the first part is played (e.g. a gun fires,
continuing with either a scream or a ricochet, depending on whether the bullet
hits).
Pitch and Volume Control
The WIN-STK allows you to specify the left and right volume for any sound,
plus its pitch. Actually, the WIN-STK allows you to control the playback length
of the sound, which affects the perceived pitch. The distinction is important,
because increases in the length decrease the pitch (make it lower).
dplay.flags = dws_dplay_SND | dws_dplay_LVOL |
dws_dplay_RVOL | dws_dplay_PITCH;
dplay.snd = sfx1;
dplay.lvol = dws_IDENTITY;
dplay.rvol = dws_IDENTITY / 2;
dplay.pitch = dws_IDENTITY * 2;
dws_DPlay(&dplay);
This example will play a sound, with the right channel softer than the left. It
will play at a lower pitch than it was recorded at.
In a 3D game, volume control of the left and right channels can be used to
indicate the direction from which the sound is coming.
Pitch can be used to break up the monotony of a sound that's played many
times. Just vary the pitch slightly each time you play it.
Interactive Digitized Audio
Now, let's take a look at what you can do with a sound once it's playing.
You could terminate it.
dws_DDiscard(dplay.soundnum);
You could terminate it, and all other instances of the same sound file:
dws_DDiscardAO(sfx1);
The "AO" stands for "All Occurrences".
To do anything sophisticated with a sound, you'll need dws_DGetInfo and
dws_DSetInfo.
Querying a Sound's Status
dws_DGetInfo can return information about a playing sound, via a
dws_DPLAY struct. You just set the flags field to indicate the fields for
which you want information.
The function knows which sound to look up based on its soundnum, so you will
need to provide that. Remember to set the dws_dplay_SOUNDNUM bit in
flags.
dplay.flags = dws_dplay_SOUNDNUM;
dplay.soundnum = sndnum_from_prior_call_to_dplay;
dws_DGetInfo(&dplay, NULL);
In the above example, we're asking for the soundnum field of the currently
playing sound. dplay.soundnum will either be unchanged, or hold a 0 if the
sound is done playing. There was no sequenced sound, so we pass NULL for
the second dplay parameter.
Changing a Sound on the Fly
You can change the loop count, priority, left and right volume, pitch, and
callback of a currently-playing (or sequenced) sound.
This example illustrates changing the left-channel volume of a sound:
dplay.flags = dws_dplay_SOUNDNUM | dws_dplay_LVOL;
dplay.soundnum = sndnum_from_prior_call_to_dplay;
dplay.lvol = dws_IDENTITY / 4;
dws_DSetInfo(&dplay, NULL);
Callbacks
The WIN-STK can give you notification when a sound starts, ends, or aborts.
This feature relies on Windows' message queue system. If you know your
window handle, and have a message handler (Window Procedure) installed for
the window, then this feature will work for you.
The following example illustrates how to play a sound, so that you'll be notified
when it's done.
dplay.flags = dws_dplay_SND | dws_dplay_CALLBACK;
dplay.snd = sfx;
dplay.hwndmsg = hwnd;
dplay.message = WM_USER + 1;
dws_DPlay(&dplay);
The sound will play once. The window whose handle is specified by hwnd will
receive the WM_USER + 1 message (you should, of course, create constants for
any messages you intend to use).
Your message handler can do anything it wants, including make WIN-STK
function calls.
Note: Your message handler must use the lParam parameter to determine
which event occured. There are three possible WIN-STK callback event types:
dws_event_SOUNDCOMPLETE, dws_event_SOUNDSTARTED, and
dws_event_SOUNDABORTED.
Playing Large Sounds Directly from Disk
If you have a very large sound files (e.g. a 3-minute 16-bit 44kHz music track),
you might want to play it directly from the disk.
Win32
Under Win32 (Windows 95 and NT), you can easily do this. The operating
system supports memory-mapped files. The following code snippet illustrates
how to do this:
void PlayDWDFile(char *filename)
{
dws_DPLAY dplay;
HANDLE hfile;
HGLOBAL hdwd;
BYTE *dwd;
hfile = CreateFile(filename, GENERIC_READ, 0,
NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
hdwd = CreateFileMapping(hfile, NULL,
PAGE_READONLY,
0L, 0L, "DWD");
dwd = (BYTE*)MapViewOfFile(hdwd, FILE_MAP_READ,
0L, 0L, 0L);
dPlay.flags = dws_dplay_SND;
dPlay.snd = dwd;
dws_DPlay(&dPlay);
/* Wait until the file is done playing */
UnmapViewOfFile(dwd);
CloseHandle(hdwd);
CloseHandle(hfile);
}
It's important to clean up by unmapping the file, and closing down the handles!
Win16
You can play large files from disk under Windows 3.1 also, though it's a little
bit more involved. You read the file one manageable chunk at a time, slap a
DWD header on each chunk, and sequence the chunk after the previous chunk.
Win32s
The WIN-STK supports Win32s on Windows 3.1x systems. DWSW32S.DLL is
the primary DLL for Win32s. It provides the entire documented WIN-STK
API. It then thunks down to DWSW16S.DLL which then makes calls into
DWSW16.DLL. The primary difference between the 16- and the main 32-bit
DLL is multithreading. Under Win32s, therefore, the WIN-STK uses the 16-bit
kernel to actually perform the work.
If you're using C/C++, the code in DWSW32.LIB will automatically determine
whether it's running under Win32s or a real Win32 environment (Windows 95
or NT). It will call into the correct DLL. This library file is equivalent to a
standard import library, though it was written in C. Its other advantage is that it
will not terminate your program if it can't find the DLL (it will instead report no
sound capabilities present-true enough without the WIN-STK DLLs).
In Win32s systems, you must install DWSW32S.DLL, DWSW16S.DLL, and
DWSW16.DLL. But, you will only need to deliver only one executable-at
least as far as the WIN-STK goes. However, there are many substantial
differences between different implementations of Win32s, especially so with
Win32s. Caveat programmer!
Note: Visual BASIC and Pascal/Delphi users do not have access to this C/C++
mechanism and must provide a separate executable file for Win32s and
Windows 95/NT.
For 32-bit VB4, if you want to make an executable which runs under Win32s,
you will need to change DWS.BAS. In each WIN-STK function declaration,
change "DWSW32.DLL" to "DWSW32S.DLL". This DLL is the correct one
for Win32s.
For 32-bit Delphi 2, if you want to make an executable which runs under
Win32s, you will need to change DWS.PAS. Change the line which contains
DWSDLL = 'DWSW32'; to DWSDLL = 'DWSW32S'; instead. This DLL is the
correct one for Win32s.
Error Handling
The WIN-STK can often tell you when you're making a mistake. All functions
have a boolean return value. A 1 means success. A 0 means an error of some
kind occurred. In this case, you should call dws_ErrNo to determine which.
if (dws_DetectHardWare(&dres) == 0)
{
err = dws_ErrNo();
DisplayErr("during dws_DetectHardWare");
}
We provide the source code to DisplayErr in C, BASIC, and Pascal. Just
look inside PLAYSTK.C, PLAYSTK.BAS, or PLAYSTK.PAS, respectively.
Reference
This section is broken down into topics for the Functions, the Errors, the Data
Structures, the Utilities, and the File Formats.
Each is the definitive specification on its subject, with a minimum of verbiage.
The Functions
There are 21 functions in the WIN-STK library.
Unless otherwise noted, you must call dws_Init before calling any other
WIN-STK function.
For each function, we give the prototypes for C, Visual BASIC, and Pascal. We
give a description, the parameters, related functions, and the complete list of
errors that the function might generate. You may assume that the list of errors is
complete; if an error is not listed for a given function, then that function cannot
flag that error.
dws_DClear
Declarations
WORD dws_DClear(void);
Declare Function dws_DClear() As Integer
function dws_DClear : WORDBOOL;
Description
This function stops all digitized sounds.
Parameters
None.
Related Functions
dws_DDiscard, dws_DDiscardAO, dws_DPlay
Errors
dws_NOTINITTED, dws_NOTSUPPORTED
dws_DDiscard
Declarations
WORD dws_DDiscard(WORD soundnum);
Declare Function dws_DDiscard(ByVal soundnum As
Integer) As Integer
function dws_DDiscard(soundnum: WORD) : WORDBOOL;
Description
This function stops the specified sound.
Parameters
soundnum number of the sound to be killed
Related Functions
dws_DClear, dws_DDiscardAO, dws_DPlay
Errors
dws_NOTINITTED, dws_NOTSUPPORTED
dws_DDiscardAO
Declarations
WORD dws_DDiscardAO(BYTE *snd);
Declare Function dws_DDiscardAO(snd As Long) As
Integer
function dws_DDiscardAO(snd: PBYTE) : WORDBOOL;
Description
This function stops all occurrences of a DWD. It's useful if you have repeatedly
played the same sound effect, and want to stop all instances.
Parameters
snd ptr to the DWD to stop
Related Functions
dws_DClear, dws_DDiscard, dws_DPlay
Errors
dws_NOTINITTED, dws_NOTSUPPORTED
dws_DetectHardWare
Declarations
WORD dws_DetectHardWare(dws_DETECTRESULTS *dr);
Declare Function dws_DetectHardWare(dr As
dws_DETECTRESULTS) as Integer
function dws_DetectHardWare(var dr: dws_DETECTRESULTS)
: WORDBOOL;
Description
This function determines the capabilities of the hardware and drivers, and also
calculates the WIN-STK's internal buffer size.
If there is more than one audio device or device driver, the WIN-STK will
choose the most capable: 16-bit is chosen over 8-bit, stereo over mono, and
higher sampling rates over lower.
Notes
You may call this function only before dws_Init, or again after dws_Kill.
Parameters
dr ptr to struct to hold the calculated information
Related Functions
dws_Init
Errors
dws_ALREADYINITTED, dws_INTERNALERROR,
dws_INVALIDPOINTER, dws_MEMORYALLOCFAILED,
dws_RESOURCEINUSE, dws_SETEVENTFAILED
dws_DGetInfo
Declarations
WORD dws_DGetInfo(dws_DPLAY *dp1, dws_DPLAY *dp2);
Declare Function dws_DGetInfo(dp1 As dws_DPLAY,
dp2 As dws_DPLAY) As Integer
function dws_DGetInfo(var dp1: dws_DPLAYREC; var dp2:
dws_DPLAYREC) : WORDBOOL;
Description
This function returns information about a playing sound, and the one sequenced
to play after it.
Parameters
dp1 ptr to struct to hold information on currently-playing sound
dp2 the same, for sequenced sound
The flags field in each struct is used to specify which fields to query. You
must indicate which sound is of interest, by using the soundnum field in at
least one struct. If you initialize the soundnum field in both structs, then both
must be the same (e.g. dp1->soundnum = dp2->soundnum). This is
because a sequenced sound always has the same sound ID number as the
playing sound.
You may query these fields: dws_dplay_SND, dws_dplay_COUNT,
dws_dplay_PRIORITY, dws_dplay_PRESND, dws_dplay_LVOL,
dws_dplay_RVOL, dws_dplay_PITCH, or dws_dplay_CALLBACK.
If dws_dplay_CALLBACK is specified, then both the hwndmsg and the
message fields are returned.
Related Functions
dws_DPlay, dws_DSetInfo
Errors
dws_D_BADDPLAY, dws_INVALIDPOINTER, dws_NOTINITTED,
dws_NOTSUPPORTED
dws_DGetRateFromDWD
Declarations
WORD dws_DGetRateFromDWD(BYTE *snd, WORD *rate);
Declare Function dws_DGetRateFromDWD(snd As Long,
rate As Integer) As Integer
function dws_DGetRateFromDWD(snd: PBYTE; var rate:
WORD) : WORDBOOL;
Description
This function returns the sampling rate of the specified DWD.
Notes
You may call this function at any time, even before dws_Init, or after
dws_Kill.
Parameters
snd ptr to the DWD of interest
rate variable which will hold the returned sampling rate, in Hz
Related Functions
dws_Init, dws_WAV2DWD
Errors
dws_D_NOTADWD, dws_D_NOTSUPPORTEDVER,
dws_INVALIDPOINTER
dws_DPause
Declarations
WORD dws_DPause(void);
Declare Function dws_DPause() As Integer
function dws_DPause : WORDBOOL;
Description
This function pauses all digitized playback.
Note: all calls after the first will have no effect until dws_DUnPause is called.
The WIN-STK does not maintain a "pause count".
Parameters
None.
Related Functions
dws_DUnPause
Errors
dws_NOTINITTED, dws_NOTSUPPORTED
dws_DPlay
Declarations
WORD dws_DPlay(dws_DPLAY *dplay);
Declare Function dws_DPlay(dplay As dws_DPLAY) As
Integer
function dws_DPlay(var dplay: dws_DPLAYREC) :
WORDBOOL;
Description
This function can play or sequence a sound.
"Sequencing" a sound causes it to play after another specified sound is done.
The dws_dplay_SYNCHRONOUS flag causes it to wait til the sound is done.
Parameters
dplay ptr to struct specifying the sound
Note
Most of the fields in the dplay struct are optional; you must set the
corresponding bit in the flags field to indicate which ones you're using.
Each field (except flags and snd) gets a reasonable default if not specified:
count = 1
priority = dws_NORMALPRIORITY
presnd = (none)
lvol = dws_IDENTITY
rvol = dws_IDENTITY
pitch = dws_IDENTITY
hwndmsg = (none)
message = (none)
Related Functions
dws_DClear, dws_DDiscard, dws_DDiscardAO, dws_DGetInfo,
dws_DSetInfo
Errors
dws_D_BADDPLAY, dws_D_NOTSUPPORTEDVER,
dws_DPlay_NOSPACEFORSOUND, dws_INVALIDPOINTER,
dws_NOTINITTED, dws_NOTSUPPORTED
dws_DSetInfo
Declarations
WORD dws_DSetInfo(dws_DPLAY *dp1, dws_DPLAY *dp2);
Declare Function dws_DSetInfo(dp1 As dws_DPLAY, dp2 As
dws_DPLAY) As Integer
function dws_DSetInfo(var dp1: dws_DPLAYREC; var dp2:
dws_DPLAYREC) : WORDBOOL;
Description
This function can change the parameters of a playing sound, and the one
sequenced to play after it.
Parameters
dp1 ptr to struct which holds new parameters for currently playing sound
dp2 the same, for sequenced sound
Note
The flags field in each struct is used to specify which fields to modify. You
must indicate which sound is of interest, by using the soundnum field in at
least one struct. If you initialize the soundnum field in both structs, then both
must be the same (e.g. dp1->soundnum = dp2->soundnum). This is
because a sequenced sound always has the same sound ID number as the
playing sound.
The following parameters may be changed dws_dplay_COUNT,
dws_dplay_PRIORITY, dws_dplay_LVOL, dws_dplay_RVOL,
dws_dplay_PITCH, and dws_dplay_CALLBACK.
If you specify dws_dplay_CALLBACK then be sure to fill in both the
hwndmsg and the message field.
Related Functions
dws_DGetInfo, dws_DPlay
Errors
dws_D_BADDPLAY, dws_INVALIDPOINTER, dws_NOTINITTED,
dws_NOTSUPPORTED
dws_DUnPause
Declarations
WORD dws_DUnPause(void);
Declare Function dws_DUnPause() As Integer
function dws_DUnPause : WORDBOOL;
Description
This function resumes digitized playback, if it was previously paused by
dws_DPause.
All sounds will continue where they left off.
Note: all calls after the first will have no effect until dws_DPause is called
again. The WIN-STK does not maintain a "pause count".
Parameters
None.
Related Functions
dws_DPause
Errors
dws_NOTINITTED, dws_NOTSUPPORTED
dws_ErrNo
Declarations
WORD dws_ErrNo(void);
Declare Function dws_ErrNo() As Integer
function dws_ErrNo : WORD;
Description
This function returns the last error triggered by a WIN-STK function. Call it
after any WIN-STK function returns failure (0 or FALSE).
Successful WIN-STK calls do not affect the return value of dws_ErrNo.
Notes
You may call this function at any time, even before dws_Init, or after
dws_Kill.
Parameters
None.
Related Functions
All.
Errors
None.
dws_Init
Declarations
WORD dws_Init(dws_DETECTRESULTS *dr, dws_IDEAL
*ideal);
Declare Function dws_Init(dr As dws_DETECTRESULTS,
ideal As dws_IDEAL) As Integer
function dws_Init(var dr: dws_DETECTRESULTS; var
ideal: dws_IDEAL) : WORDBOOL;
Description
This function configures and initializes the sound device drivers and the WIN-
STK internals. Most STK calls won't work until after this call.
The exceptions are dws_DetectHardWare, dws_DGetRateFromDWD,
dws_ErrNo, and dws_WAV2DWD.
Parameters
dr ptr to struct which holds the output from dws_DetectHardWare
ideal ptr to struct specifying some WIN-STK mode parameters
Related Functions
dws_DetectHardWare, dws_Kill
Errors
dws_ALREADYINITTED, dws_Init_BUFTOOSMALL,
dws_INTERNALERROR, dws_INVALIDPOINTER,
dws_MEMORYALLOCFAILED, dws_NOTSUPPORTED,
dws_RESOURCEINUSE, dws_SETEVENTFAILED
dws_Kill
Declarations
WORD dws_Kill(void);
Declare Function dws_Kill() As Integer
function dws_Kill : WORDBOOL;
Description
This function kills the WIN-STK.
If you have successfully called dws_Init, then you must call this function
before your program terminates.
Parameters
None.
Related Functions
dws_Init
Errors
dws_NOTINITTED
dws_MClear
Declarations
WORD dws_MClear(void);
Declare Function dws_MClear() As Integer
function dws_MClear : WORDBOOL;
Description
This function kills the music playback.
Parameters
None.
Related Functions
dws_MPlay
Errors
dws_INTERNALERROR, dws_NOTINITTED, dws_NOTSUPPORTED
dws_MPause
Declarations
WORD dws_MPause(void);
Declare Function dws_MPause() As Integer
function dws_MPause : WORDBOOL;
Description
This function pauses music playback.
Note: all calls after the first will have no effect until dws_MUnPause is called.
The WIN-STK does not maintain a "pause count".
Parameters
None.
Related Functions
dws_MUnPause
Errors
dws_NOTSUPPORTED, dws_NOTINITTED
dws_MPlay
Declarations
WORD dws_MPlay(dws_MPLAY *mplay);
Declare Function dws_MPlay(mplay As dws_MPlay) As
Integer
function dws_MPlay(var mplay: dws_MPLAYREC) :
WORDBOOL;
Description
This function starts playing a MIDI song. For WIN-STK version 1, the MIDI
song must be played from disk. Version 2 will play from a memory buffer.
Notes
When specifying the MIDI filename, be sure to use the full pathname.
Parameters
mplay ptr to struct specifying the song
Related Functions
dws_MPause, dws_MSongStatus
Errors
dws_INTERNALERROR, dws_INVALIDPOINTER, dws_NOTINITTED,
dws_NOTSUPPORTED, dws_M_BADMPLAY
dws_MSongStatus
Declarations
WORD dws_MSongStatus(WORD *result);
Declare Function dws_MSongStatus(result As Integer) As
Integer
function dws_MSongStatus(var result: WORD) : WORDBOOL;
Description
This function returns the status of the music playback engine.
Parameters
result ptr to a variable to hold the returned status:
0 //no song loaded
dws_MSONGSTATUSPLAYING //song playing
dws_MSONGSTATUSPAUSED //no song loaded, STK paused
dws_MSONGSTATUSPLAYING | dws_MSONGSTATUSPAUSED //Song
loaded but paused
Related Functions
dws_MPause, dws_MPlay, dws_MUnPause
Errors
dws_INVALIDPOINTER, dws_NOTINITTED, dws_NOTSUPPORTED
dws_MUnPause
Declarations
WORD dws_MUnPause(void);
Declare Function dws_MUnPause() As Integer
function dws_MUnPause : WORDBOOL;
Description
This function resumes music playback, if it was previously paused by
dws_MPause.
The music will continue where it left off.
Note: all calls after the first will have no effect until dws_MPause is called
again. The WIN-STK does not maintain a "pause count".
Parameters
None.
Related Functions
dws_MPause
Errors
dws_NOTINITTED, dws_NOTSUPPORTED
dws_Update
Declarations
WORD dws_Update(void);
Declare Function dws_Update() As Integer
function dws_Update : WORDBOOL;
Description
This function keeps the digitized sound going, even if your application is
hogging the CPU. Under normal circumstances, calling this function shouldn't
be necessary with the 32-bit WIN-STK DLL. In a 16-bit program, on the other
hand, you may need to call dws_Update to prevent sound skipping, unless
you are scrupulous about yielding time to the system frequently. We
recommend an interval of 55ms (18.2 Hz).
Notes
The Windows API timeSetEvent can be used to give you a callback during
each hardware timer interrupt. During such callbacks, most Windows API calls
are off-limits; Windows is not reentrant. dws_Update makes function calls
which are in this category. Calling it from an interrupt-time callback will crash
Windows!
Parameters
None.
Related Functions
None.
Errors
dws_NOTINITTED
dws_WAV2DWD
Declarations
WORD dws_WAV2DWD(BYTE *wave, DWORD *len, BYTE *dwd);
Declare Function dws_WAV2DWD(wave As Long, len As
Long, dwd As Long) As Integer
function dws_WAV2DWD(wave: PBYTE; var len: DWORD; snd:
PBYTE) : WORDBOOL;
Description
This function can convert a WAV-format buffer to DWD-format. DWD is the
digitized sound format used by DiamondWare's Sound ToolKit.
Notes
There are two usages of this function. The first returns the buffer length
required to hold the DWD. The second converts the WAV to DWD format.
Notes
You may call this function at any time, even before dws_Init, or after
dws_Kill.
Parameters
Usage 1
wave ptr to buffer containing a valid WAV file
len length of the WAV buffer
dwd NULL
Usage 2
wave ptr to WAV buffer
len length of the WAV (input), size of DWD (output)
dwd ptr to a buffer to hold the DWD output
Related Functions
dws_DGetRateFromDWD, dws_DPlay
Errors
dws_INTERNALERROR, dws_INVALIDPOINTER,
dws_WAV2DWD_NOTAWAVE, dws_WAV2DWD_UNSUPPORTEDFORMAT
dws_XDig
Declarations
WORD dws_XDig(WORD lvolume, WORD rvolume);
Declare Function dws_XDig(ByVal lvolume As Integer,
ByVal rvolume As Integer) As Integer
function dws_XDig(lvolume, rvolume: WORD) : WORDBOOL;
Description
This function allows you to control the overall volume for digitized sound
output.
Parameters
lvolume left volume, 0=off, dws_IDENTITY=normal, 65535=MAX
rvolume same, for right channel
Related Functions
dws_DPlay
Errors
dws_NOTINITTED, dws_NOTSUPPORTED
The Errors
There are 16 errors (plus one non-error) which may be generated by a WIN-
STK function.
0 dws_EZERO
This is a non-error. dws_ErrNo will return this if you call it before any WIN-
STK function triggers an error.
1 dws_NOTINITTED
The STK was not initialized when you called an STK function.
2 dws_ALREADYINITTED
This call cannot be made after the STK is initialized.
3 dws_NOTSUPPORTED
The installed hardware, or current WIN-STK mode doesn't support the
requested feature (music or sound).
4 dws_INTERNALERROR
The STK encountered an invalid internal state. Please report this to
DiamondWare.
5 dws_INVALIDPOINTER
You passed an invalid pointer to a function. Under Win32, the WIN-STK can
sometimes catch this type of problem and trigger an error.
6 dws_RESOURCEINUSE
The WIN-STK tried to open a device driver, but it was already opened by
another program.
7 dws_MEMORYALLOCFAILED
The WIN-STK tried to allocate some memory, but was denied.
8 dws_SETEVENTFAILED
The WIN-STK tried to set an event semaphore, but was denied.
9 dws_BUSY
The WIN-STK is currently processing something; please try your call again
later. This error can only occur in 16-bit programs, and if you're calling the
WIN-STK from an interrupt handler or equivalent. The error cannot occur in
32-bit programs, because the WIN-STK is thread-safe.
101 dws_Init_BUFTOOSMALL
You tried to set the buffer size in the dws_IDEAL struct to something which
was obviously too small.
201 dws_D_NOTADWD
The DWD buffer you passed did not contain a DWD file.
202 dws_D_NOTSUPPORTEDVER
The DWD buffer you passed contained an unknown or unsupported version of
DWD file.
203 dws_D_BADDPLAY
You set up a dws_DPLAY struct which was not valid for the function called.
Note: dws_DGetInfo and dws_DSetInfo require the soundnum field to
specify the sound.
251 dws_DPlay_NOSPACEFORSOUND
This is more of a warning than an error. It's telling you that there are no sound
slots left, and that the priority of your new sound was too low to displace any
playing sound.
301 dws_WAV2DWD_NOTAWAVE
The WAV buffer you passed did not contain a WAV file.
302 dws_WAV2DWD_UNSUPPORTEDFORMAT
The WAV buffer you passed contained an unknown or unsupported version of
WAV file.
401 dws_M_BADMPLAY
You set up a dws_MPLAY struct which was not valid for the function called.
The Data Structures
There are 4 structure types provided by the WIN-STK. Their formats and
specifications are detailed here.
dws_DETECTRESULTS
This struct is filled in by dws_DetectHardWare. The digbfr field is user-
writable, but use caution.
Note: information is stored in the reserved field. If you're writing this struct
out to a file, make sure to write out the entire contents. Failure to do this may
result in unpredictable behavior!
Name Size Description
muscaps 4 *bitwise OR of available music devices
digcaps 4 +bitwise OR of available WAV modes
digbfr 4 buffer size calculated by autodetect
reserved 20 undocumented
*The music devices are dws_muscap_MIDIPORT (external MIDI port, MPU-
401 adapter or compatible, wavetable board, etc.), dws_muscap_SYNTH (a
generic internal synthesizer), dws_muscap_SQSYNTH (a square-wave synth),
dws_muscap_FMSYNTH (FM synthesizer), and dws_muscap_MAPPER (the
MIDI mapper). If there is no MIDI capability installed in the machine, then the
muscaps field will be set to dws_muscap_NONE.
+The WAV modes are dws_digcap_11025_08_1,
dws_digcap_11025_08_2, dws_digcap_11025_16_1,
dws_digcap_11025_16_2, dws_digcap_22050_08_1,
dws_digcap_22050_08_2, dws_digcap_22050_16_1,
dws_digcap_22050_16_2, dws_digcap_44100_08_1,
dws_digcap_44100_08_2, dws_digcap_44100_16_1, and
dws_digcap_44100_16_2. If there is no WAV capability in the machine,
then the digcaps field will be set to dws_digcap_NONE.
The format of each constant is dws_digcap_<sampling rate in Hz>_<bits per
sample>_<number of channels> (e.g. dws_digcap_22050_08_2 for 22kHz
8-bit stereo).
dws_IDEAL
This struct allows you to control the mode and features that the WIN-STK will
set up when it initializes.
Name Size Description
flags 4 *bitwise OR of options
mustyp 4 preferred MIDI device
digtyp 4 preferred WAV output mode
dignvoices 2 max digitized voices to mix
reserved 18 undocumented
*The possible flags are dws_ideal_SWAPLR (if the left and right channels
are reversed by the hardware, the WIN-STK can swap them to compensate),
dws_ideal_DISABLEPITCH (for extra speed, disable pitch changing on
slow machines with one simple flag), dws_ideal_DISABLEVOLUME (for
even more speed, disable volume changing), and dws_ideal_MAXSPEED (a
shortcut to disable the pitch and volume change feature). Specify
dws_ideal_NONE if you don't want any of these options.
dws_DPLAY
This struct is used for playing or sequencing a digitized sound (the dws_DPlay
function). It's also used for querying a playing or sequenced sound (the
dws_DGetInfo function) and reprogramming a playing or sequenced sound
(the dws_DSetInfo function).
Name Size Description
flags 4 *bitfield specifying fields used
snd 4 pointer to DWD buffer
count 2 number of times to play; 0=infinite
priority 2 +higher numbers = higher priorities
presnd 2 soundnum of sound to sequence after
soundnum 2 number assigned to this sound
lvol 2 left volume, 0-dws_IDENTITY-65535
rvol 2 the same, for the right channel
pitch 2 #playback length
dummy 2 pads next field to dword boundary
hwndmsg ^4 =handle of window to send msgs to
message ^4 message ID to send
reserved ^18 undocumented
*There is a bitfield flag corresponding to each field in this struct, except that
hwndmsg and message must be specified as a pair, and so get only one flag.
Additionally, some flags directly control functional behavior, and so do not
correspond to any field in the struct. The flags are dws_dplay_SND,
dws_dplay_COUNT, dws_dplay_PRIORITY, dws_dplay_PRESND,
dws_dplay_SOUNDNUM, dws_dplay_LVOL, dws_dplay_RVOL,
dws_dplay_PITCH, dws_dplay_CALLBACK,
dws_dplay_SYNCHRONOUS, dws_dplay_FIRSTSAMPLE,
dws_dplay_CURSAMPLE, and dws_dplay_LASTSAMPLE. For each field
in the struct you use, set the corresponding bit in flags.
+If the program tries to play more sounds than specified in the dws_IDEAL
struct passed to dws_Init, then the lowest priority sound will be dropped.
#The pitch field actually controls the playback length. In other words, lower
values mean higher frequencies, and higher values mean lower (and slower)
playback. As with volume change, dws_IDENTITY means no change in
volume.
^Sizes are given for the 32-bit DLL. For the 16-bit DLL, hwndmsg and
message are both 2 bytes. reserved is 22 bytes.
=When the WIN-STK send you a window message, the wParam parameter
holds the soundnum, and lParam holds dws_event_SOUNDCOMPLETE,
dws_event_SOUNDSTARTED, or dws_event_SOUNDABORTED.
dws_MPLAY
This struct is used for playing a MIDI song by the dws_MPlay function.
Name Size Description
track 4 0-terminated filename of MIDI song
count 2 number of times to play; 0=infinite
reserved 10 undocumented
The Utilities
We provide two utilities, PLAYSTK (with source in C, Visual BASIC, and
Pascal) and WAV2DWD. Both include 16- and 32-bit versions.
PLAYSTK
PLAYSTK is provided mostly as a source-code example of how to use the
WIN-STK. It's also useful as a test to see if the machine is working. It can play
several digitized sounds (.WAV or .DWD format) plus a song (.MID format) at
the same time.
It's implemented as a dialog box. On the right side are sliders for volume and
pitch control. These affect all new sounds played, and they'll also change the
most recent currently playing sound. There is a check box to reverse the left
and right channels. And there are three radio buttons to control sampling rate.
The program is hard-wired for 8-bit stereo output.
The New button will bring up a dialog box which allows you to open any
.WAV, .DWD, or .MID file.
The Play button will start whichever sound or song is selected in the listbox.
Double-clicking on a listbox item will also play it.
The Stop button will stop all noise.
The Remove button will delete the selected listbox item.
Operation should be straightforward and intuitive. The source code shows you
many WIN-STK programming techniques.
WAV2DWD
This program is provided to make batch conversion of a large number of WAV
files easy. The WIN-STK can convert WAV buffers to DWD at runtime. But if
you know what files you need in advance, then converting them off-line is the
best way to go.
This program is implemented as a dialog box.
There are three windows on the left side to control the source (WAV) file
selections. They are drive, directory, and file listboxes. The three windows on
the right side control drive and directory for the output (DWD) plus show
(without any user control) the list of DWD files in the output directory.
Once you've set up your source and destination directories, select one or more
WAV files to convert. Hit the Convert button, and DWD files quickly appear.
8-bit mono WAVs convert to DWDs which are also suitable for use with the
DOS-STK.
The File Formats
WIN-STK version 1 uses one file format specified by DiamondWare. It's called
DWD (DiamondWare Digitized).
The specification is provided here in the hope that it may be useful to you.
Permission is hereby granted to use this specification in the creation of any
software. The specification itself is, of course, protected by United States law
and international treaty provisions.
DWD Header
Byte # Description
00-22 "DiamondWare Digitized\n\0"
23 1A (EOF to abort printing of file)
24 Major version number
25 Minor version number
26-29 Unique sound ID (checksum XOR timestamp)
30 Reserved
31 Compression type (0=none)
32-33 Sampling rate (in Hz)
34 Number of channels (1=mono, 2=stereo)
35 Number of bits per sample (8, 16)
36-37 Absolute value of largest sample in file
38-41 length of data section (in bytes)
42-45 # samples (16-bit stereo is 4 bytes/sample)
46-49 Offset of data from start of file (in bytes)
50-53 Reserved for future expansion (markers)
54-55 Padding
??-?? Future expansion (heed the 2 offsets, above!)
About DWD Version Numbers
The DWD specification v1.0, finalized in 1994, did not need modification to
support the WIN-STK. However, due to a slight oversight, the DOS-STK does
not reject DWD files which are stereo and/or 16-bit, even though it cannot
correctly play them (there was no software which could generate such files back
then). We can't recall that product, so we are incrementing the version # of the
file.
8-bit mono DWD files with no compression should be marked as version 1.0.
The DOS- or WIN-STK can correctly play these files. If a DWD file contains
two (or more) channels, 16 (or more) bits per sample, or compression, then it
must be marked as version 1.1, which will be rejected by the DOS-STK. Our
WAV2DWD utility generates files according to this version numbering scheme.
The WIN-STK will attempt to play any file of version 1.x (unlike the DOS-
STK). Any future enhancements to the file format which break backwards
compatibility will jump to 2.0 or higher for this reason.
Sample Format
Samples are stored as signed data. That is, each 8-bit sample ranges from -128
to +127. 16-bit samples range from -32768 to +32767.
Monophonic files are stored in order, from sample 0 to sample N.
Stereophonic files are stored in order, with the left channel of each sample
preceding the right.
DWD File Format Clarification, September 8, 1996
Starting at byte 56, and continuing to the offset of the sound data (which is
specified in the DWORD at bytes 46-49), there is room for additional text
information fields (e.g. title, copyright, comments, etc.)
So long as the offset-to-data field is correct, all code written to play or
parse DWD files (going back to the DOS-STK v1.0) will continue to work
correctly.
Each text string in this new section must be NULL-terminated, and the entire
section should itself be NULL-terminated. Also, just like the environment-
variable model from which this borrows, each string will be of the format:
<name>=value.
In all fields which might contain multiple names (e.g. keywords, editor), we
recommend that you separate each value with a semicolon and a space (e.g. Bob
Miller; John Smith). It will help, with such digital editors as CoolEdit.
For the same reason, do not use any newlines.
Each of the following fields is optional, and may occur in any order:
TITLE
This brief name should describe the digital sound, but be short enough for
display in a listbox.
ORGARTIST
The name of the author of the original sound, before digital editing.
GENRE
Metal, jazz, classical, instrument, sound effect, etc.
KEYWORDS
For searching.
DIGSRC
Describe the source format (e.g. AAD CD), digitizer used (e.g. SB 16), etc.
ORGMEDIUM
Voice, orchestra, industral site, etc.
EDITOR
The name(s) of the editor(s) who worked on the file, or edited it in any way.
Give credit where credit is due.
DIGITIZER
The name of the person who digitized the file.
COMMENT
Please end each sentence with a period.
SUBJECT
Describes the subject matter recorded.
SRC
The source of the sound: a record label, studio engineer, or whomever
actually recorded it.
COPYRIGHT
Example: Copyright 1996, DiamondWare, Ltd. All Rights Reserved.
SOFTWARE
The program used to edit this file.
CREATEDATE
The date of the original recording. Use yyyy-mm-dd format (e.g. 1996-09-08).
Appendix
Changes from the Sound ToolKit for DOS
If you have used DiamondWare's Sound ToolKit for DOS, you may wish to
skim most of the manual and study this section.
In all cases we have attempted to preserve the same API and behavior as in the
DOS version. Some changes, many bona fide enhancements, were required or
made possible by the move to Windows.
We'll go over the changes to the data structures, functions, behavior, errors,
samples, and utility software.
Data Structures
Note: we changed all occurrences of byte, word, and dword to BYTE,
WORD, and DWORD, to conform to the Windows convention.
Pascal Note
The DOS-STK used explicit pointer syntax. The WIN-STK now uses the var
keyword.
dws_DETECTOVERRIDES
In Windows, the sound driver deals with the port, DMA, and IRQ settings, so
the STK doesn't need to try to autodetect them. This struct was originally
provided to override the autodetect, and has been completely eliminated in the
WIN-STK.
dws_DETECTRESULTS
Forget everything you learned about this structure under DOS. Its purpose is
still the same: to store the results of the autodetect. But under Windows, we're
detecting buffer size, driver and hardware capabilities, not hardware settings.
You might want to read about this structure in the Reference section.
dws_IDEAL
digrate has been merged into digtyp, which is now a bitfield. Read the
section on the dws_IDEAL struct for details on how this works.
In Windows, there is often a choice of music output devices (with different
levels of sound quality). The muscaps field in the dws_DETECTRESULTS
struct tells you which drivers are installed. The mustyp field in the
dws_IDEAL struct allows you to specify which one to use.
There is now a flags field, which allows you to disable volume and/or pitch
changing support (for slower machines). It also allows you to specify that the
left and right channels should be swapped (to compensate for wiring problems
downstream).
dws_DPLAY
This structure has been greatly expanded, due to the integration of volume/pitch
change functionality into the kernel, and the new support for stereo.
You should set the first field, flags, to indicate which of the rest of the fields
you're using. In most cases, unused fields will assume reasonable defaults--see
the complete discussion in the Reference section for details.
snd, count, priority, presnd, and soundnum work as they did in the
DOS version.
We added lvol and rvol to control the left and right volume of the sound.
Note: Both mono and stereo source sounds will play in stereo, so long as the
output mode is stereo.
pitch controls the playback rate of the sound. More specifically, it controls
the length of the sound during playback. Thus higher numbers correspond to
slower and lower sounds, and lower numbers correspond to faster and higher
sounds.
For normal playback, use dws_IDENTITY for lvol, rvol, and pitch.
The WIN-STK can notify you when a sound is done playing. For this feature,
use the last two fields: hwndmsg and message. The WIN-STK will send
message ID message to the window whose handle is hwndmsg. In this
message, the wParam parameter holds the soundnum, and the lParam
parameter holds dws_event_SOUNDCOMPLETE (future versions will support
more types of events).
dws_MPLAY
The track field is now a NULL-terminated string holding the filename of the
MIDI song to play (future versions will again play music from memory buffers).
Functions
We removed some functions, added a few new ones, and changed one.
Removed
dws_DGetRate
dws_DSetRate
dws_DSoundStatus
dws_XMaster
dws_XMusic
dwt_*
The playback rate cannot be changed while the STK is running under Windows.
However, the built-in DSP can compensate for the odd sound recorded at a
different sampling rate (there will be some sound quality loss, however).
dws_DSoundStatus has been replaced with dws_DGetInfo, which is
much more powerful. This function pairs well with dws_DSetInfo.
In Windows, the user can change the mixer volumes at will using the control
panel. Therefore, it's unnecessary (and counter to the Windows paradigm) for
an application to gratuitously change them. Thus, we've eliminated
dws_XMaster and dws_XMusic. Below, read what we've done with
dws_XDig.
Because implementing a timer like the DWT is trivial in Windows, and because
the WIN-STK doesn't require you to call dws_Update frequently and
periodically (see below), we're no longer providing the DWT.
Added
dws_DGetInfo
dws_DSetInfo
dws_WAV2DWD
dws_DGetInfo will return you a full dws_DPLAY structure full of
information about a playing or sequenced sound. You can change most of the
fields, and then call dws_DSetInfo. See the Reference section for details.
dws_WAV2DWD allows you to convert WAV files to DWD format at runtime.
Changed
dws_Update
dws_XDig
In the DOS-STK, dws_Update kept the music playing; if you didn't call it,
you didn't get music. We provided the optional DWT module to take care of
this, or you could call it from your own hardware time handler. All of this stuff
is unnecessary in Windows.
But Windows (version 3.x) causes other problems. Each application runs until it
voluntarily yields time to the system and other applications. "Normal"
applications are supposed to play nicely, and yield frequently. If an application
hogs the system, all other apps (and the Windows GUI) freeze until the hog
yields. This is bad enough (though often tolerated) with productivity
applications. But it's totally unacceptable for sound to stop and then resume
playing a quarter-second later. The discontinuity jars the listener.
Games and multimedia applications can generally assume that they're not
sharing the system with email, word processors, spreadsheets, etc. But they do
often spend significant time in tight loops, and sometimes it's quite inconvenient
to yield time to the system.
If your Windows 3.x application needs to hog the system for a while, call
dws_Update periodically; we recommend an interval of 55ms (18.2 times per
second). This will keep the sound rolling under 3.x (the only way to stop it is to
drag your application by the title bar). Under 95/NT, the 32-bit version of the
WIN-STK is multithreaded, though the function is fully enabled, and works as it
does under 16 bits.
dws_XDig no longer controls the hardware mixer. Instead, it controls our
internal software mixer. Thus, it makes it easy to quickly lower or raise (subject
to clipping distortion) the overall digitized volume level. dws_XMusic (and
dws_XMaster) will return with WIN-STK v2, which will provide much
greater control over MIDI music.
dws_XDig now takes two parameters, to support stereo. And these parameters
are 0 to 256 (dws_IDENTITY) to 65535, rather than 0-255 in the DOS version.
The ability to make digitized playback louder via dws_XDig is new for the
WIN-STK.
Behavior
Some changes in behavior are noted above in the discussions of the various data
structures and functions. Below, in no particular order, are some other changes
of which you should be aware.
In the DOS-STK, the digitized buffer size was a purely internal issue. Our
research and testing determined the buffer size. We compiled it into the STK,
and it just worked. Unfortunately, under Windows, the buffer size must change
from system to system. Why? Because larger buffers are less susceptible to
skipping, but smaller buffers provide lower latency (the time between the call to
dws_DPlay and when the user actually hears the sound). Slower machines
therefore require larger buffers. Buffer size determination is a non-trivial
calculation, which is performed during dws_DetectHardWare. You might
provide your user a slider bar with some amount of control over buffer size, to
optimize on his machine the tradeoff between latency and skipless playback.
After the call to dws_DetectHardWare, you can change digbfr slightly
(go easy!) according to the user's input. Of course, most of the time, the
autodetect routine will do its job properly, and you won't need to monkey with
this setting. Unless there's a problem with skipping, leave it alone.
The DOS version dropped low-priority sounds out when the dynamic range of
the hardware would otherwise be exceeded. The WIN-STK can clip sounds on
a sample-by-sample basis. Each sound must still have a priority so that if the
maximum number of sounds is exceeded, the kernel knows in which order to
drop sounds.
The DOS version supported only 8-bit mono sound. The WIN-STK supports 8-
and 16-bit source sounds in both mono and stereo, and can play using drivers in
8- or 16-bit, mono or stereo modes. It will perform all necessary conversions.
The DOS version was restricted to sounds smaller than 64K. Both the 16- and
32-bit WIN-STK DLLs support sounds up to 4G in length.
The 32-bit WIN-STK DLL can trap exceptions caused by invalid user-supplied
pointers, and flag them with an error return value.
For WIN-STK version 1, music is played directly from .MID files on disk.
Version 2 will play from memory and provide interactivity and runtime control
of music. Therefore, we say a temporary goodbye to the .DWM file (it will
return!) There is also no control of FM-instrument patches with the WIN-STK.
Errors
Many errors are unnecessary under Windows, and have been eliminated. We've
added some new ones too. As with the DOS version, the main manual lists all
possible errors which can be flagged by each routine.
You might want to read the Error listing in the Reference section.
Samples
PLAYSTK.C
PLAYSTK.BAS
PLAYSTK.PAS
The samples all compile into PLAY16.EXE or PLAY32.EXE, which is a single
sample applet for both music and sound.
Utility Programs
We eliminated VOC2DWD.EXE (VOC files are dying along with DOS) and
MID2DWM.EXE (this version of the WIN-STK does not use .DWM files).
We now provide WAV2DWD.EXE, which functionality is also available to
your application on-line via the WIN-STK library.